我們可以使用new F()這樣的構造函數創建一個新object,如果F.prototype是一個object,那new操作符會使用這個object設定為新object的[[prototype]]。
這邊的prototype只是F這個構造函數的一個屬性。
let animal = {
eats: true
};
function Cat(name) {
this.name = name;
}
Cat.prototype = animal;
let cat = new Cat("White cat"); // cat.__proto__ == animal
console.log( cat.eats ); // true
設置Cat.prototype = animal的字面意思是,當創建了new Cat時,會把創建的object的[[prototype]]指向animal。
F.prototype只有在new F時才會用到,如果在創建後,F.prototype有了變化(F.prototype = {anothoer object}),已經存在的obejct會保持舊有的繼承,但是之後創建的objetc會繼承新的。
每個函數都有prototype屬性,即使提供它。默認的prototype是一個只有constructor屬性的object,屬性constructor指向函數自身。
function Cat() {}
/* default prototype
Cat.prototype = { constructor: Cat };
*/
可以檢查一下 :
function Cat() {}
// by default:
// Cat.prototype = { constructor: Cat }
console.log( Cat.prototype.constructor == Cat ); // true
所以如果我們什麼都不做,constructor屬性可以透過[[prototype]]繼承給所有cat使用:
function Cat() {}
// by default:
// Cat.prototype = { constructor: Cat }
let cat = new Cat(); // inherits from {constructor: Cat}
console.log(cat.constructor === Cat); // true (from prototype)
我們可以使用constructor屬性來創建一個新object。
function Cat(name) {
this.name = name;
alert(name);
}
let cat = new Cat("White cat");
let cat2 = new cat.constructor("Black cat");
當我們有一個object,但是不知道它使用了哪個構造器(例如它來自第三方library),並且我們需要一個類似的object,這時候這種方法就很方便。
但是這裏需要注意的是,JavaScript並不能確保正確的constructor函數值。constructor只是默認存在函數的prototype,一但我們主動把它替換掉,constructor就不存在了。 例如:
function Cat() {}
Cat.prototype = {
jumps: true
};
let cat = new Cat();
console.log(cat.constructor === Cat); // false
因此為了確保正確的constructor,我們可以選擇添加/刪除屬性到默認的prototype,而不是將整個覆蓋:
function Cat() {}
Cat.prototype.jumps = true
或是手動重新創建constructor屬性:
Cat.prototype = {
jumps: true,
constructor: Cat
};
如此一來就能確保正確的constructor。